home *** CD-ROM | disk | FTP | other *** search
/ Delphi Magazine Collection 2001 / Delphi Magazine Collection 20001 (2001).iso / DISKS / Issue58 / System / GroupBoxEx.pas next >
Encoding:
Pascal/Delphi Source File  |  2000-05-06  |  12.1 KB  |  365 lines

  1. unit GroupBoxEx;
  2.  
  3. interface
  4.  
  5. uses
  6.   Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
  7.  
  8. type
  9.     TGroupBoxCaptionPos = ( gbTopLeft, gbTopMiddle, gbTopRight,
  10.                             gbBottomLeft, gbBottomMiddle, gbBottomRight,
  11.                             gbLeftTop, gbLeftMiddle, gbLeftBottom,
  12.                             gbRightTop, gbRightMiddle, gbRightBottom );
  13.  
  14.     // Custom procedures
  15.     TGroupBoxEnableDisableQuery = procedure (Sender: TObject; Control: TControl; Enabled: Boolean; var Handled: Boolean) of Object;
  16.     TGroupBoxPaintCaptionBackground = procedure (Sender: TObject; Canvas: TCanvas; const Rect: TRect; var Handled: Boolean) of Object;
  17.  
  18.     TGroupBoxOptions = class (TPersistent)
  19.     private
  20.         fOnChange: TNotifyEvent;
  21.         fCaptionSpaces: Boolean;
  22.         fShowBorder: Boolean;
  23.         fCaptionFont: TFont;
  24.         fCaptionPos: TGroupBoxCaptionPos;
  25.         procedure Changed;
  26.         procedure CaptionFontChanged (Sender: TObject);
  27.         procedure SetShowBorder (Value: Boolean);
  28.         procedure SetCaptionPos (Value: TGroupBoxCaptionPos);
  29.         procedure SetCaptionFont (Value: TFont);
  30.         procedure SetCaptionSpaces (Value: Boolean);
  31.     public
  32.         constructor Create;
  33.         destructor Destroy; override;
  34.     published
  35.         property OnChange: TNotifyEvent read fOnChange write fOnChange;
  36.         property CaptionSpaces: Boolean read fCaptionSpaces write SetCaptionSpaces default True;
  37.         property ShowBorder: Boolean read fShowBorder write SetShowBorder default True;
  38.         property CaptionPos: TGroupBoxCaptionPos read fCaptionPos write SetCaptionPos default gbTopLeft;
  39.         property CaptionFont: TFont read fCaptionFont write SetCaptionFont;
  40.     end;
  41.  
  42.     TCustomGroupBoxEx = class (TCustomGroupBox)
  43.     private
  44.         fOptions: TGroupBoxOptions;
  45.         fOnEnableDisableQuery: TGroupBoxEnableDisableQuery;
  46.         fOnGroupBoxPaintCaptionBackground: TGroupBoxPaintCaptionBackground;
  47.         procedure OptionsChanged (Sender: TObject);
  48.         procedure CMEnabledChanged (var Msg: TMessage); message cm_EnabledChanged;
  49.     protected
  50.         procedure AdjustClientRect (var Rect: TRect); override;
  51.         procedure Paint; override;
  52.         procedure PaintCaption (Str: String);
  53.     public
  54.         constructor Create (AOwner: TComponent); override;
  55.         destructor Destroy; override;
  56.         property Advanced: TGroupBoxOptions read fOptions write fOptions;
  57.         property OnEnableDisableQuery: TGroupBoxEnableDisableQuery read fOnEnableDisableQuery write fOnEnableDisableQuery;
  58.         property OnPaintCaptionBackground: TGroupBoxPaintCaptionBackground read fOnGroupBoxPaintCaptionBackground write fOnGroupBoxPaintCaptionBackground;
  59.     end;
  60.  
  61.     TGroupBoxEx = class (TCustomGroupBoxEx)
  62.     published
  63.         property Align;
  64.         property Anchors;
  65.         property BiDiMode;
  66.         property Caption;
  67.         property Color;
  68.         property Constraints;
  69.         property Ctl3D;
  70.         property DockSite;
  71.         property DragCursor;
  72.         property DragKind;
  73.         property DragMode;
  74.         property Enabled;
  75.         property Font;
  76.         property ParentBiDiMode;
  77.         property ParentColor;
  78.         property ParentCtl3D;
  79.         property ParentFont;
  80.         property ParentShowHint;
  81.         property PopupMenu;
  82.         property ShowHint;
  83.         property TabOrder;
  84.         property TabStop;
  85.         property Visible;
  86.         property OnClick;
  87.         property OnContextPopup;
  88.         property OnDblClick;
  89.         property OnDragDrop;
  90.         property OnDockDrop;
  91.         property OnDockOver;
  92.         property OnDragOver;
  93.         property OnEndDock;
  94.         property OnEndDrag;
  95.         property OnEnter;
  96.         property OnExit;
  97.         property OnGetSiteInfo;
  98.         property OnMouseDown;
  99.         property OnMouseMove;
  100.         property OnMouseUp;
  101.         property OnStartDock;
  102.         property OnStartDrag;
  103.         property OnUnDock;
  104.         property Advanced;
  105.         property OnEnableDisableQuery;
  106.         property OnPaintCaptionBackground;
  107.     end;
  108.  
  109. procedure Register;
  110.  
  111. implementation
  112.  
  113. { TGroupBoxOptions }
  114.  
  115. uses ComCtrls;
  116.  
  117. constructor TGroupBoxOptions.Create;
  118. begin
  119.     Inherited Create;
  120.     fCaptionPos := gbTopLeft;
  121.     fCaptionSpaces := True;
  122.     fCaptionFont := TFont.Create;
  123.     fCaptionFont.OnChange := CaptionFontChanged;
  124.     fShowBorder := True;
  125. end;
  126.  
  127. destructor TGroupBoxOptions.Destroy;
  128. begin
  129.     fCaptionFont.Destroy;
  130.     Inherited Destroy;
  131. end;
  132.  
  133. procedure TGroupBoxOptions.Changed;
  134. begin
  135.     if Assigned (fOnChange) then fOnChange (Self);
  136. end;
  137.  
  138. procedure TGroupBoxOptions.CaptionFontChanged (Sender: TObject);
  139. begin
  140.     Changed;
  141. end;
  142.  
  143. procedure TGroupBoxOptions.SetCaptionSpaces (Value: Boolean);
  144. begin
  145.     if fCaptionSpaces <> Value then begin
  146.         fCaptionSpaces := Value;
  147.         Changed;
  148.     end;
  149. end;
  150.  
  151. procedure TGroupBoxOptions.SetCaptionFont (Value: TFont);
  152. begin
  153.     fCaptionFont.Assign (Value);
  154.     Changed;
  155. end;
  156.  
  157. procedure TGroupBoxOptions.SetCaptionPos (Value: TGroupBoxCaptionPos);
  158. begin
  159.     if fCaptionPos <> Value then begin
  160.         fCaptionPos := Value;
  161.         Changed;
  162.     end;
  163. end;
  164.  
  165. procedure TGroupBoxOptions.SetShowBorder (Value: Boolean);
  166. begin
  167.     if fShowBorder <> Value then begin
  168.         fShowBorder := Value;
  169.         Changed;
  170.     end;
  171. end;
  172.  
  173. { TCustomGroupBoxEx }
  174.  
  175. constructor TCustomGroupBoxEx.Create(AOwner: TComponent);
  176. begin
  177.     Inherited Create (AOwner);
  178.     fOptions := TGroupBoxOptions.Create;
  179.     fOptions.OnChange := OptionsChanged;
  180. end;
  181.  
  182. destructor TCustomGroupBoxEx.Destroy;
  183. begin
  184.     fOptions.Free;
  185.     Inherited Destroy;
  186. end;
  187.  
  188. procedure TCustomGroupBoxEx.OptionsChanged (Sender: TObject);
  189. begin
  190.     Invalidate;
  191. end;
  192.  
  193. procedure TCustomGroupBoxEx.AdjustClientRect (var Rect: TRect);
  194. begin
  195.     // Don't pass this on to Inherited.....
  196. end;
  197.  
  198. procedure TCustomGroupBoxEx.CMEnabledChanged (var Msg: TMessage);
  199. var
  200.     Idx: Integer;
  201.     Child: TControl;
  202.     Handled: Boolean;
  203. begin
  204.     Inherited;
  205.     Invalidate;
  206.     // Now enable or disable all the contained controls
  207.     for Idx := 0 to ControlCount - 1 do begin
  208.         Child := Controls [Idx];
  209.         // Query application to see if we should do it
  210.         Handled := False;
  211.         if Assigned (fOnEnableDisableQuery) then fOnEnableDisableQuery (Self, Child, Enabled, Handled);
  212.         if not Handled then begin
  213.             Child.Enabled := Enabled;
  214.  
  215.             if Child.ClassName = 'TEdit' then begin
  216.                 if Enabled then TEdit (Child).Color := clWindow
  217.                 else TEdit (Child).Color := clBtnFace;
  218.             end;
  219.  
  220.             if Child.ClassName = 'TListBox' then begin
  221.                 if Enabled then TListBox (Child).Color := clWindow
  222.                 else TListBox (Child).Color := clBtnFace;
  223.             end;
  224.  
  225.             if Child.ClassName = 'TComboBox' then begin
  226.                 if Enabled then TComboBox (Child).Color := clWindow
  227.                 else TComboBox (Child).Color := clBtnFace;
  228.             end;
  229.  
  230.             if Child.ClassName = 'TMemo' then begin
  231.                 if Enabled then TMemo (Child).Color := clWindow
  232.                 else TMemo (Child).Color := clBtnFace;
  233.             end;
  234.  
  235.             if Child.ClassName = 'TDateTimePicker' then begin
  236.                 if Enabled then TDateTimePicker (Child).Color := clWindow
  237.                 else TDateTimePicker (Child).Color := clBtnFace;
  238.             end;
  239.  
  240.             // Add your own type-specific preferences here?
  241.         end;
  242.     end;
  243. end;
  244.  
  245. procedure TCustomGroupBoxEx.Paint;
  246. var
  247.     R: TRect;
  248.     H2: Integer;
  249. begin
  250.     with Canvas do begin
  251.         Font := fOptions.CaptionFont;
  252.         H2 := TextHeight ('0') div 2 - 1;
  253.         case fOptions.fCaptionPos of
  254.             gbTopLeft..gbTopRight:
  255.                 R := Rect (0, H2, Width, Height);
  256.             gbBottomLeft..gbBottomRight:
  257.                 R := Rect (0, 0, Width, Height - H2);
  258.             gbLeftTop..gbLeftBottom:
  259.                 R := Rect (H2, 0, Width, Height);
  260.             gbRightTop..gbRightBottom:
  261.                 R := Rect (0, 0, Width - H2, Height);
  262.         end;
  263.  
  264.         if Ctl3D then begin
  265.             Inc(R.Left);
  266.             Inc(R.Top);
  267.             Brush.Color := clBtnHighlight;
  268.             if fOptions.ShowBorder then FrameRect(R);
  269.             OffsetRect (R, -1, -1);
  270.             Brush.Color := clBtnShadow;
  271.         end else Brush.Color := clWindowFrame;
  272.         if fOptions.ShowBorder then FrameRect(R);
  273.  
  274.         if Text <> '' then PaintCaption (Text);
  275.     end;
  276. end;
  277.  
  278. procedure TCustomGroupBoxEx.PaintCaption (Str: String);
  279. var
  280.     R: TRect;
  281.     lf: TLogFont;
  282.     tm: TTextMetric;
  283.     BackgroundHandled: Boolean;        
  284.     X, Y, Flags, TH, TW: Integer;
  285. begin
  286.     if fOptions.CaptionSpaces then Str := ' ' + Str + ' ';
  287.     if fOptions.CaptionPos in [gbLeftTop, gbRightBottom] then Str := Str + ' ';
  288.  
  289.     BackgroundHandled := False;
  290.     TH := Canvas.TextHeight (Str);
  291.     TW := Canvas.TextWidth (Str);
  292.  
  293.     // Deal with the easy stuff first !
  294.     if fOptions.CaptionPos in [gbTopLeft..gbBottomRight] then begin
  295.         R := Rect (8, 0, Width - 16, TH);
  296.         if fOptions.CaptionPos in [gbBottomLeft..gbBottomRight] then OffsetRect (R, 0, Height - TH);
  297.  
  298.         Flags := dt_SingleLine;
  299.         case fOptions.CaptionPos of
  300.             gbTopLeft, gbBottomLeft:     Flags := Flags or dt_Left;
  301.             gbTopMiddle, gbBottomMiddle: Flags := Flags or dt_Center;
  302.             gbTopRight, gbBottomRight:   Flags := Flags or dt_Right;
  303.         end;
  304.  
  305.         if Assigned (OnPaintCaptionBackground) then
  306.             OnPaintCaptionBackground (Self, Canvas, R, BackgroundHandled);
  307.  
  308.         Canvas.Brush.Color := Color;
  309.         if BackgroundHandled then SetBkMode (Canvas.Handle, Transparent);
  310.         if Enabled then DrawText (Canvas.Handle, PChar (Str), -1, R, Flags) else begin
  311.             SetTextColor (Canvas.Handle, ColorToRGB (clBtnHighlight));
  312.             DrawText (Canvas.Handle, PChar (Str), -1, R, Flags);
  313.             OffsetRect (R, -1, -1);
  314.             SetBkMode (Canvas.Handle, Transparent);
  315.             SetTextColor (Canvas.Handle, ColorToRGB (clBtnShadow));
  316.             DrawText (Canvas.Handle, PChar (Str), -1, R, Flags);
  317.         end;
  318.     end else begin
  319.         R := Rect (0, 8, TH, Height - 16);
  320.         if fOptions.CaptionPos in [gbRightTop..gbRightBottom] then OffsetRect (R, Width - TH, 0);
  321.  
  322.         // This is only going to work with TrueType fonts....
  323.         GetTextMetrics (Canvas.Handle, tm);
  324.         if (tm.tmPitchAndFamily and tmpf_TrueType) = 0 then Exit;
  325.  
  326.         if Assigned (OnPaintCaptionBackground) then
  327.             OnPaintCaptionBackground (Self, Canvas, R, BackgroundHandled);
  328.  
  329.         // Now build a new, vertical font.....
  330.         GetObject (Canvas.Font.Handle, sizeOf (lf), @lf);
  331.         if fOptions.CaptionPos in [gbLeftTop..gbLeftBottom] then lf.lfEscapement := 900
  332.         else lf.lfEscapement := 2700;
  333.         Canvas.Font.Handle := CreateFontIndirect (lf);
  334.  
  335.         Canvas.Brush.Color := Color;
  336.         X := R.Left;  Y := R.Top;
  337.         case fOptions.CaptionPos of
  338.             gbLeftTop,    gbRightTop:     Y := 8 + TW;
  339.             gbLeftMiddle, gbRightMiddle:  Y := ((Height - TW) div 2) + TW;
  340.             gbLeftBottom, gbRightBottom:  Y := Height - 16;
  341.         end;
  342.  
  343.         if lf.lfEscapement = 2700 then begin
  344.             Dec (Y, TW);  Inc (X, TH);
  345.         end;
  346.  
  347.         if BackgroundHandled then SetBkMode (Canvas.Handle, Transparent);
  348.         if Enabled then ExtTextOut (Canvas.Handle, X, Y, 0, Nil, PChar (Str), Length (Str), Nil) else begin
  349.             SetTextColor (Canvas.Handle, ColorToRGB (clBtnHighlight));
  350.             ExtTextOut (Canvas.Handle, X, Y, 0, Nil, PChar (Str), Length (Str), Nil);
  351.             Dec (X);  Dec (Y);
  352.             SetBkMode (Canvas.Handle, Transparent);
  353.             SetTextColor (Canvas.Handle, ColorToRGB (clBtnShadow));
  354.             ExtTextOut (Canvas.Handle, X, Y, 0, Nil, PChar (Str), Length (Str), Nil);
  355.         end;
  356.     end;
  357. end;
  358.  
  359. procedure Register;
  360. begin
  361.     RegisterComponents ('Experimental', [TGroupBoxEx]);
  362. end;
  363.  
  364. end.
  365.